package ac.github.oa.internal.core.ui

import ac.github.oa.api.common.Matcher
import ac.github.oa.internal.core.ui.Sell.FLAP
import ac.github.oa.internal.core.ui.Sell.ITEMS
import ac.github.oa.internal.core.ui.Sell.SUBMIT
import ac.github.oa.internal.core.ui.Sell.default
import ac.github.oa.internal.core.ui.Sell.icon
import ac.github.oa.internal.core.ui.Sell.itemP
import ac.github.oa.internal.core.ui.Sell.keywords
import ac.github.oa.internal.core.ui.Sell.noneKeywords
import ac.github.oa.internal.core.ui.Sell.submitItem0
import ac.github.oa.internal.core.ui.Sell.submitItem1
import ac.github.oa.internal.core.ui.Sell.title
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.InventoryHolder
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import taboolib.common.platform.event.SubscribeEvent
import taboolib.module.nms.getName
import taboolib.platform.compat.depositBalance
import taboolib.platform.util.isAir
import taboolib.platform.util.modifyMeta
import taboolib.platform.util.sendLang

class SellUI(val player: Player) : InventoryHolder {

    val items = mutableMapOf<Int, Data>()

    var power: Double = -1.0

    private val inventory = Bukkit.createInventory(this, 3 * 9, title)

    companion object {

        @SubscribeEvent
        fun e(e: InventoryCloseEvent) {
            val inventory = e.inventory
            val holder = inventory.holder as? SellUI ?: return
            val player = e.player
            ITEMS.forEach {
                val itemStack = inventory.getItem(it) ?: return@forEach
                if (itemStack.isAir()) return@forEach
                player.inventory.addItem(itemStack)
                inventory.setItem(it, null)
            }
        }

        @SubscribeEvent
        fun e(e: InventoryClickEvent) {
            val inventory = e.inventory
            val holder = inventory.holder as? SellUI ?: return
            val player = e.whoClicked as Player

            if (holder.power != -1.0) {
                e.isCancelled = true
            }

            if (e.rawSlot in FLAP) {
                e.isCancelled = true
                return
            }

            if (e.rawSlot == SUBMIT) {
                e.isCancelled = true
                if (holder.power == -1.0) {
                    holder.power = 0.0
                    ITEMS.forEach {
                        val itemStack = inventory.getItem(it) ?: return@forEach
                        if (itemStack.isAir()) return@forEach
                        if (!isSell(itemStack)) return@forEach
                        holder.items[it] = Data(itemStack).also {
                            holder.power += it.power
                        }
                    }
                    if (holder.items.isEmpty()) {
                        holder.power = -1.0
                        return
                    }
                    inventory.setItem(SUBMIT, submitItem1.modifyMeta<ItemMeta> {
                        setDisplayName(displayName.replace("{count}", holder.power.toString()))
                        lore = lore?.flatMap {
                            if (it.contains("\$item")) {
                                holder.toList(it)
                            } else {
                                listOf(it.replace("{count}", holder.power.toString()))
                            }
                        }
                    })
                } else {
                    holder.items.forEach { inventory.setItem(it.key, null) }
                    player.depositBalance(holder.power)
                    player.sendLang("item-sell-successful", holder.power)
                    holder.power = -1.0
                    holder.items.clear()
                    inventory.setItem(SUBMIT, submitItem0)
                }
            }


        }

        fun getPower(itemStack: ItemStack): Double {
            val list = itemStack.itemMeta?.lore ?: emptyList()
            val string = list.firstOrNull { s1 -> keywords.any { it in s1 } } ?: return default * itemStack.amount
            return Matcher.single(string).amount * itemStack.amount
        }

        fun isSell(itemStack: ItemStack): Boolean {
            val list = itemStack.itemMeta?.lore ?: emptyList()
            return list.any { s1 -> noneKeywords.any { it !in s1 } }
        }
    }

    fun build() {
        FLAP.forEach { inventory.setItem(it, icon) }
        inventory.setItem(SUBMIT, submitItem0)
        player.openInventory(inventory)
    }

    class Data(val itemStack: ItemStack) {

        val name = itemStack.getName()

        val amount = itemStack.amount

        val power = getPower(itemStack)

    }

    fun toList(string: String): List<String> {
        return items.values.map {
            string.replace(
                "\$item",
                itemP.replace("{0}", it.name).replace("{1}", it.amount.toString()).replace("{2}", it.power.toString())
            )
        }
    }

    override fun getInventory(): Inventory {
        return inventory
    }

}